package com.celeritymq.configure;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Locale;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.celeritymq.dispatcher.Dispatcher;
import com.celeritymq.logging.LoggerFactory;
import static com.celeritymq.configure.Base.*;

public class PropertiesConfigure implements Configure {
	private Logger log = LoggerFactory.getLogger(getClass());
	private String configPath;
	private boolean initialized = false;
	private static Configure reader = new PropertiesConfigure();

	private PropertiesConfigure() {
	}

	public static Configure getInstance() {
		return reader;
	}

	public synchronized void configure() throws Exception {
		if (initialized) {
			log.log(Level.FINE, "configure has already initialized");
			return;
		}
		configPath = System.getProperty("configPath", "config");
		if (configPath == null || configPath.trim().equals("")) {
			log.log(Level.SEVERE, "Please set configPath before server start");
			throw new ExceptionInInitializerError("Please set configPath before server start");
		}
		log.log(Level.INFO, "configure configPath[" + configPath + "]");
		if (!configPath.endsWith(File.separator)) {
			configPath = configPath + File.separator;
		}
		Base.configPath = configPath;
		File baseFile = new File(configPath + BASE);
		// log.log(Level.INFO, "configure base file["+(configPath + BASE)+"]");
		if (!baseFile.exists()) {
			log.log(Level.SEVERE, "configure base file[" + (configPath + BASE) + "] does not exist");
			throw new ExceptionInInitializerError("base file[" + configPath + BASE + "] does not exist");
		}
		Properties props = read(configPath + BASE);
		Locale locale = new Locale(props.getProperty(ConfigConstants.LOCALE, "en"));
		log.log(Level.INFO, "configure locale[" + locale + "]");
		String dateFormat = props.getProperty(ConfigConstants.DATE_FORMAT, "ddMMMMyyyy");
		log.log(Level.INFO, "configure date format[" + dateFormat + "]");
		String ip = props.getProperty(ConfigConstants.DESTINATION_BIND_IP, "127.0.0.1");
		log.log(Level.INFO, "configure bind ip[" + ip + "]");
		int port = Integer.parseInt(props.getProperty(ConfigConstants.DESTINATION_BIND_PORT, "9999"));
		log.log(Level.INFO, "configure bind port[" + port + "]");
		Base.destination_ip = ip;
		Base.destination_port = port;
		Base.locale = locale;
		Base.dateFormat = dateFormat;

		String monitorConfig = Base.configPath + "monitor.properties";
		Properties monitorProps = read(monitorConfig);
		for (Object key : monitorProps.keySet()) {
			String dispatcherName = monitorProps.getProperty((String) key);
			Dispatcher dispatcher = (Dispatcher) Class.forName(dispatcherName).newInstance();
			Base.dispatchers.put((String) key, dispatcher);
		}
		initialized = true;
	}

	private Properties read(String cfgFile) {
		File file = new File(cfgFile);
		if (!file.exists()) {
			file = new File(configPath + cfgFile);
			if (!file.exists()) {
				return null;
			}
		}
		Properties props = new Properties();
		try {
			props.load(new FileInputStream(file));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return props;

	}

	// private Set<Hotel> initHotelConfig(String[] hotelList) {
	// Set<Hotel> hotelSet = new HashSet<Hotel>();
	// for (String hotelName : hotelList) {
	// hotelName = hotelName.trim();
	// log.log(Level.INFO, "init hotel file["+hotelName+"]");
	// String hotelFileName = configPath + hotelName + ".cfg";
	// if (!new File(hotelFileName).exists()) {
	// log.log(Level.WARNING,
	// "configure hotel file["+hotelFileName+"] does not exist");
	// throw new
	// ExceptionInInitializerError("configure hotel file["+hotelFileName+"] does not exist");
	// }
	// Properties hotelProps = read(hotelFileName);
	// int rating = Integer.parseInt(hotelProps.getProperty(RATING));
	// // 加载regular参数
	// int regularWeekday = Integer.parseInt(hotelProps.getProperty(REGULAR +
	// "/" + WEEKDAY));
	// log.log(Level.INFO,
	// "init hotel file["+hotelName+"] REGULAR WEEKDAY["+regularWeekday+"]");
	// int regularWeekend = Integer.parseInt(hotelProps.getProperty(REGULAR +
	// "/" + WEEKEND));
	// log.log(Level.INFO,
	// "init hotel file["+hotelName+"] REGULAR WEEKEND["+regularWeekend+"]");
	// int rewardWeekday = Integer.parseInt(hotelProps.getProperty(REWARD + "/"
	// + WEEKDAY));
	// log.log(Level.INFO,
	// "init hotel file["+hotelName+"] REGULAR WEEKDAY["+rewardWeekday+"]");
	// int rewardWeekend = Integer.parseInt(hotelProps.getProperty(REWARD + "/"
	// + WEEKEND));
	// log.log(Level.INFO,
	// "init hotel file["+hotelName+"] REGULAR WEEKEND["+rewardWeekend+"]");
	// Hotel hotel = new Hotel(hotelName, rating, new int[] { regularWeekday,
	// regularWeekend }, new int[] { rewardWeekday,
	// rewardWeekend });
	// hotelSet.add(hotel);
	// }
	// return hotelSet;
	// }

	@Override
	public boolean isInitialized() {
		return initialized;
	}

}
